package example.controller;

import java.io.File;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.multipart.commons.CommonsMultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import util.MapUtil;
import example.service.EmpService;

@Controller
/*
@RequestMapping在类名上面定义，相当于指定的URL是此控制器内的所有其它访问路径的父路径。
如果在某个方法上面定义@RequestMapping注解，则相对于父路径来说，是其子路径。
如果不定义value值，那么按父路径访问就会被默认执行。
但请注意，默认的访问方式只能有一个。
——以上，from OSC
*/
/*
 * 实际访问路径可以为/emp/add.* --> 伪静态化
 */
@RequestMapping("/emp")
public class EmpController extends BaseController{
	private EmpService empService;
	@Autowired
	public void setEmpService(EmpService empService) {
		this.empService = empService;
	}

	/*
	 * 设置URL访问地址。它有两个属性 —— 
	 * value：指定访问路径
	 * method：指定指定请求方式，请求方式在RequestMethod这个类中，全部以常量形式定义，它默认使用GET请求。
	 * @RequestMapping("/emp") 等价于  @RequestMapping(value = "/emp", method = RequestMethod.GET)
	 * ——以上，from OSC
	 */
//	@RequestMapping(method = {RequestMethod.GET, RequestMethod.POST})
	@RequestMapping(method = {RequestMethod.GET})
	public String showList(Model model, HttpServletRequest request) {
		/*
		 * Model是用来渲染数据，生成页面用的。
		 * Model以及另一个ModelMap，都是作为视图模型传递参数的，它们的作用域为request。
		 * 除此之外，你还可以定义HttpServletRequest、HttpServletResponse等等各种各样的参数。
		 * ——以上，from OSC
		 */
		model.addAttribute("list", empService.getEmpList());
		
		//获取controller重定向传递的参数，见editSave方法，参数拼接在最终显示url后
		System.out.println("跳转来源：" + request.getParameter("resource"));
		
		//获取controller重定向传递的参数，见addSave方法，参数不拼接
		System.out.println("redirect传递参数：" + request.getSession().getAttribute("attribute"));
				
		return "emp/list";
	}
	
	@RequestMapping(value = "", method = RequestMethod.POST)
	public String search(Model model, HttpServletRequest request) {
		Map params = MapUtil.mapToStringMap(request.getParameterMap());
		
		List empList = empService.searchEmp(params);
		model.addAttribute("list", empList);
		
		return "emp/list";
	}
	
	@RequestMapping(value = "/page/{pageNum}", method = {RequestMethod.POST, RequestMethod.GET})
	public String pagingUrl(Model model, HttpServletRequest request, @PathVariable String pageNum) {
		Map params = MapUtil.mapToStringMap(request.getParameterMap());
		params.put("pageNum", pageNum);
		
		Map pagingInfo = this.empService.searchEmpPaging(params);
		
		model.addAttribute("pagingInfo", pagingInfo);
		
		return "emp/pagingUrl";
	}
	
	@RequestMapping(value = "/page", method = RequestMethod.GET)
	public String showPagingAjax(Model model, HttpServletRequest request) {
		Map params = MapUtil.mapToStringMap(request.getParameterMap());
		
		Map pagingInfo = this.empService.searchEmpPaging(params);
		
		model.addAttribute("pagingInfo", pagingInfo);
		
		return "emp/pagingAjax";
	}
	
	@RequestMapping(value = "/page", method = RequestMethod.POST)
	public String pagingAjax(Model model, HttpServletRequest request) {
		Map params = MapUtil.mapToStringMap(request.getParameterMap());
		
		Map pagingInfo = this.empService.searchEmpPaging(params);
		
		model.addAttribute("pagingInfo", pagingInfo);
		
		return "emp/pagingAjaxContent";
	}
	
	@RequestMapping(value = "/add")
	public String showAdd() {
		return "emp/add";
	}
	
	@RequestMapping(value = "/add", method = RequestMethod.POST) //使用相同路径，根据method区分
	public String addSave(HttpServletRequest request, ModelMap model, RedirectAttributes attr) {
//		Map params = request.getParameterMap();
		String empno = request.getParameter("empno");
		String ename = request.getParameter("ename");
		String sal = request.getParameter("sal");
		System.out.println("empno:" + empno + "; ename:" + ename + "; sal:" + sal);
		
		//重定向同时传递参数，不会出现在地址栏中，重定向方法中可以不对参数处理，页面可自动获取
		//原理是放到session中，session在跳到页面后马上移除对象
		//**注意** 是addFlashAttribute
		//另一个方法addAttribute，参数会显示在地址栏中
		attr.addFlashAttribute("attribute", "addSave");
		
		return "redirect:/emp";//重定向路径
	}
	
	@RequestMapping(value = "/{empno}/edit", method = RequestMethod.GET)
	public String showEdit(Model model, @PathVariable String empno) {
		model.addAttribute("emp", empService.getEmpByEmpno(empno));
		return "emp/edit";
	}
	
	@RequestMapping(value = "/{empno}/edit", method = RequestMethod.POST)
	public ModelAndView editSave(@PathVariable String empno) {
		System.out.println(" ---------------------------  EmpController: editSave()");
//		empService.updateEmp();
		empService.updateEmpException();
		
		//重定向同时传递参数，目标地址可通过request.getParameter()获取参数
		//同时参数会拼接到地址后在地址栏中显示，形如emp?resource=edit
		ModelMap map = new ModelMap();
		map.put("resource", "edit");
		return new ModelAndView("redirect:/emp", map);
//		return "redirect:/emp";
	}
	
	@RequestMapping(value="/upload",method = RequestMethod.GET)
	public String showUpload() {
		return "emp/upload";
	}
	
	/**
	 * 单个文件上传
	 * @param request
	 * @return
	 */
	@RequestMapping(value="/upload",method = RequestMethod.POST)
	public String uploadSave(HttpServletRequest request, 
							 @RequestParam("fileName") CommonsMultipartFile file) {
		//文件类型
		System.out.println("文件类型：" + file.getContentType());
		//文件大小
		System.out.println("文件大小：" + file.getSize());
		//文件名称
		System.out.println("文件名称：" + file.getOriginalFilename());
		
		try {
		//文件是否存在
		if(!file.isEmpty()) {
			String fileName = file.getOriginalFilename();
//			String path = "userfiles" + File.separator + "upload" + File.separator + "emp" + File.separator + fileName;
			String path = "userfiles" + File.separator + "upload" + File.separator + "emp" + File.separator 
						  + String.valueOf(System.currentTimeMillis()) + fileName.substring(fileName.lastIndexOf('.'));
			String realPath = request.getSession().getServletContext().getRealPath(path);
			System.out.println("realPath: " + realPath);
			//上传到发布环境E:\workspace4_3\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\SpringMVC
			//项目中没有文件
			file.transferTo(new File(realPath));
		}
		} catch(Exception e) {
			e.printStackTrace();
		}

		return "redirect:/emp";
	}
	
	/**
	 * 多文件上传
	 * @param request
	 * @return
	 */
	@RequestMapping(value="/upload2",method = RequestMethod.POST)
	public String uploadSave2(HttpServletRequest request) {
		try {
			//设置上下文
			CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver(request.getSession().getServletContext());
			
			//检查form是否有enctype="multipart/form-data"
			if(multipartResolver.isMultipart(request)) {
				MultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest) request;
				Iterator<String> iter = multiRequest.getFileNames();
				//input控件需要有不同的name属性值，同名的只识别第一个
				while(iter.hasNext()) {
					String iterStr = iter.next();
					System.out.println(iterStr);
					MultipartFile file = multiRequest.getFile(iterStr);
					if(null != file) {
						String fileName = file.getOriginalFilename();
						System.out.println("OriginalFilename: " + fileName);
//						String path = "userfiles" + File.separator + "upload" + File.separator + "emp" + File.separator + fileName;
						String path = "userfiles" + File.separator + "upload" + File.separator + "emp" + File.separator 
									  + String.valueOf(System.currentTimeMillis()) + fileName.substring(fileName.lastIndexOf('.'));
						String realPath = request.getSession().getServletContext().getRealPath(path);
						System.out.println("realPath: " + realPath);
						//上传到发布环境E:\workspace4_3\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\SpringMVC
						//项目中没有文件
						file.transferTo(new File(realPath));
					}
				}
			}
		} catch(Exception e) {
			e.printStackTrace();
		}
		return "redirect:/emp";
	}
	
	
	@RequestMapping(value = "/{empno}/put", method = RequestMethod.GET)
	public String showPut(Model model, @PathVariable String empno) {
		model.addAttribute("emp", empService.getEmpByEmpno(empno));
		return "emp/put";
	}
	
	//接收PUT请求
	@RequestMapping(value = "/{empno}", method = RequestMethod.PUT)
	public String putSave(@PathVariable String empno) {
		System.out.println(" ---------------------------  EmpController: putSave()");
		
		return "redirect:/emp";
	}
	
	
	/*
	 * ajax开发中在请求服务器端的响应时, 对于每一种返回类型 规范的做法是要在服务端指定response的contentType 的
	 * (当然 不指定绝大多数情况下也没什么问题 尤其是返回"非xml"的时候) 。
 	 * 常遇到下面的几种情况:
		1、 服务端需要返回一段普通文本给客户端：Content-Type="text/plain"
		2 、服务端需要返回一段HTML代码给客户端：Content-Type="text/html"
		3 、服务端需要返回一段XML代码给客户端：Content-Type="text/xml"
		4 、服务端需要返回一段javascript代码给客户端 ：Content-Type="text/javascript" (标准写法应为application/javascript，但一些老旧浏览器不支持)
		5 、服务端需要返回一段json串给客户端：Content-Type="application/json"
	 * 
	 */
	//接收DELETE请求，返回普通字符串
	@RequestMapping(value = "/{empno}", method = RequestMethod.DELETE, produces="text/plain; charset=utf-8")//指定返回内容格式，并转码
	@ResponseBody 
	public String deleteSave(@PathVariable String empno, HttpServletRequest request) {
		String zwparam = request.getParameter("zwparam");
		System.out.println(" ---------------------------  EmpController: deleteSave() " + " | empno: " + empno + " | zwparam: " + zwparam);
		
		return "返回值";
	}
	
	//接收ajax请求，返回JSON
	@RequestMapping(value = "/{empno}", method = RequestMethod.DELETE, produces="application/json; charset=utf-8")
	@ResponseBody 
	public String returnJSON(@PathVariable String empno, HttpServletRequest request) {
		String zwparam = request.getParameter("zwparam");
		System.out.println(" ---------------------------  EmpController: deleteSave() " + " | empno: " + empno + " | zwparam: " + zwparam);
		
		return "返回值";
	}
} 
